package com.feiwo.nonego.rpc.consumer;

import com.feiwo.nonego.rpc.consumer.common.RpcConsumer;
import com.feiwo.nonego.rpc.proxy.api.ProxyFactory;
import com.feiwo.nonego.rpc.proxy.api.async.IAsyncObjectProxy;
import com.feiwo.nonego.rpc.proxy.api.config.ProxyConfig;
import com.feiwo.nonego.rpc.proxy.api.object.ObjectProxy;
import com.feiwo.nonego.rpc.registry.ZookeeperRegistryService;
import com.feiwo.nonego.rpc.registry.api.RegistryService;
import com.feiwo.nonego.rpc.registry.api.config.RegistryConfig;
import com.feiwo.nonego.rpc.registry.api.enums.RegistryType;
import com.feiwo.nonego.rpc.registry.api.exception.RegistryException;
import com.feiwo.nonego.rpc.spi.loader.ExtensionLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 *
 * @author feiwo 2025-08-08
 */
public class RpcClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(RpcClient.class);

    /**
     * 调用超时时间, 默认15秒
     */
    private static final long DEFAULT_TIMEOUT = 15000;

    /**
     * 服务版本
     */
    private final String serviceVersion;

    /**
     * 服务分组
     */
    private final String serviceGroup;

    /**
     * 序列化类型
     */
    private final String serializationType;

    /**
     * 动态代理类型
     */
    private final String proxy;

    /**
     * 是否异步调用
     */
    private final boolean async;

    /**
     * 是否单向调用
     */
    private final boolean oneway;

    /**
     * 调用超时时间
     */
    private long timeout = DEFAULT_TIMEOUT;

    private final RegistryService registryService;


    public RpcClient(String serviceVersion, String serviceGroup, String serializationType, boolean async, boolean oneway, long timeout, String registryAddress, RegistryType registryType, String proxy, String loadBalancerType) {
        this.serviceVersion = serviceVersion;
        this.serviceGroup = serviceGroup;
        this.serializationType = serializationType;
        this.async = async;
        this.oneway = oneway;
        this.timeout = timeout;
        this.proxy = proxy;
        this.registryService = this.getRegistryService(registryAddress, registryType, loadBalancerType);
    }

    public <T> T create(Class<T> clazz) {
        var proxy = ExtensionLoader.getExtension(ProxyFactory.class, this.proxy);
        proxy.init(new ProxyConfig<T>(clazz, serviceVersion, serviceGroup, RpcConsumer.getInstance(), serializationType, async, oneway, timeout, this.registryService));
        return proxy.getProxy(clazz);
    }

    public <T> IAsyncObjectProxy createAsync(Class<T> clazz) {
        return new ObjectProxy<T>(clazz, serviceVersion, serviceGroup, RpcConsumer.getInstance(), serializationType, async, oneway, timeout, this.registryService);
    }

    public void shutdown() {
        RpcConsumer.getInstance().close();
    }

    private RegistryService getRegistryService(String serviceName, RegistryType registryType, String loadBalancerType) {
        var registryService = new ZookeeperRegistryService();
        try {
            registryService.init(new RegistryConfig(serviceName, registryType, loadBalancerType));
        } catch (Exception e) {
            LOGGER.error("Rpc Client init registry throws ex ---> ", e);
            throw  new RegistryException(e.getMessage(), e);
        }
        return registryService;
    }
}
